<?php
/* OO-PHP : Treat data in PHP like an object.
 * This code is released under the GNU General Public License v3.
 * For more details about this license, visit http://www.gnu.org/licenses/gpl.txt */
 
interface TypeHandler {
    public function __construct($data);
    public function set($to);
    public function __toString();
    public function equals($compare);
}
class String implements TypeHandler {
    private $data;
    const INCLUDE_WHITESPACE = true;
    public function __construct($data) {
	$this->data = (string) $data;
	$this->original = (string) $data;
    }
    public function set($to) {
	$this->data = (string) $to;
    }
    public function __toString() {
	return $this->data;
    }
    public function write() {
	echo $this->data;
	return $this;
    }
    public function toUpperCase() {
	$this->set(strtoupper($this->data));
	return $this;
    }
    public function toLowerCase() {
	$this->set(strtolower($this->data));
	return $this;
    }
    public function append($text, $whitespace = false) {
	$new = $whitespace ? $this->data." ".$text : $this->data.$text;
	$this->set($new);
	return $this;
    }
    public function prepend($text, $whitespace = false) {
	$new = $whitespace ? $text." ".$this->data : $text.$this->data;
	$this->set($new);
	return $this;
    }
    public function replace($original, $with) {
	$this->set(str_replace($original, $with, $this->data));
	return $this;
    }
    public function repeat($times) {
	$this->set(str_repeat($this->data, $times));
	return $this;
    }
    public function length() {
	return strlen($this->data);
    }
    public function contains($string) {
	return FALSE !== strpos($this->data, $string);
    }
    public function positionOf($string) {
	return strpos($this->data, $string);
    }
    public function encodeEntities() {
	$this->set(htmlentities($this->data, ENT_QUOTES));
	return $this;
    }
    public function decodeEntities() {
	$this->set(html_entity_decode($this->data, ENT_QUOTES));
	return $this;
    }
    public function escape() {
	$this->set(addslashes($this->data));
	return $this;
    }
    public function urlEncode() {
	$this->set(rawurlencode($this->data));
	return $this;
    }
    public function urlDecode() {
	$this->set(rawurldecode($this->data));
    }
    public function toInteger() {
	return new Integer($this->data);
    }
    public function toEpoch() {
	$this->set(strtotime($this->data));
	return $this;
    }
    public function values($vars) {
	if(!is_array($vars))
	    return $this;
	    
	foreach($vars as $var => $val)
	    if(is_array($val))
		foreach($val as $k => $v)
		    $this->set(str_replace(":{$var}.{$k}", $v, $this->data));
	    else
		$this->set(str_replace(":{$var}", $val, $this->data));
		
	return $this;
    }
    public function equals($compare) {
	return $this->data === $compare;
    }
}
/* PROBLEM: Integer::__toString() [called when object is referenced as an integer] returns
 * a string. No workaround has been found as of late.
 * Contributions are welcome. */
class Integer implements TypeHandler {
    private $data;
    const INCLUDE_WHITESPACE = true;
    const PI = 3.14159265358979323846264338327950;
    public function __construct($data) {
	$this->data = (integer) $data;
	$this->original = (integer) $data;
    }
    public function set($to) {
	$this->data = (integer) $to;
    }
    public function __toString() {
	return (string) $this->data;
    }
    public function write() {
	echo $this->data;
	return $this;
    }
    public function toString() {
	return new String($this->data);
    }
    public function times($by) {
	$this->set($this->data * (integer) $by);
	return $this;
    }
    public function add($num) {
	$this->set($this->data + (integer) $num);
	return $this;
    }
    public function divide($by) {
	$this->set($this->data / (integer) $by);
	return $this;
    }
    public function subtract($much) {
	$this->set($this->data - (integer) $much);
	return $this;
    }
    public function base() {
	$this->set(intval($this->data));
	return $this;
    }
    public function equals($compare) {
	return $this->data === $compare;
    }
}
function string($data) {
    return new String($data);
}
function str($data) {
    return new String($data);
}
function integer($data) {
    return new Integer($data);
}
function number($data) {
    return new Integer($data);
}
function int($data) {
    return new Integer($data);
}
function create($from) {
    if(is_string($from))
	return new String($from);
	
    if(is_numeric($from))
	return new Integer($from);
	
    return $from;
}